#include "smartthread.h"

#include <chrono>
#include <iostream>
#include <sstream>

using namespace std;

int SmartThread::_intervalMs = 10;

bool SmartThread::_runFlag = true;
bool SmartThread::_blockFlag = true;

std::condition_variable SmartThread::_condvab;
std::mutex SmartThread::_mtx;

std::function<int()> SmartThread::_func;

SmartThread::SmartThread()
{
}

SmartThread *SmartThread::instance()
{
    static SmartThread ins;
    return &ins;
}

SmartThread::~SmartThread()
{
    _runFlag = false;

    if(_thd.joinable()){
        _thd.join();
    }
}

void SmartThread::setFunc(const std::function<int ()> func)
{
    _func = func;

    _thd = std::thread(majorFunc);
    notify();
    //
    _thd.detach();
}

void SmartThread::notify()
{
    _condvab.notify_one();
    _blockFlag = false;
}

void SmartThread::block()
{
    _blockFlag = true;
}

void SmartThread::majorFunc()
{
    cout<<"smartThread before while"<<endl;

    std::ostringstream oss;
    oss << std::this_thread::get_id();
    std::string stid = oss.str();
    unsigned long long tid = std::stoull(stid);
    cout<<"smart thread tid:"<<tid<<endl;

    while(_runFlag){
        if(_blockFlag){
            cout<<"smartThread-block before"<<endl;
            //
            std::unique_lock<std::mutex> ulk(_mtx);
            _condvab.wait(ulk);
            //
            cout<<"smartThread-block after"<<endl;
        }
        //task func
        _func();
        //
        std::this_thread::sleep_for(
                    std::chrono::milliseconds(
                        _intervalMs));
    }
    cout<<"smartThread after while"<<endl;
}
